import {Promise} from 'es6-promise';
import {Location} from "../core/types";
import * as utils from '../core/utils';
import {Collection, ObjectID} from "mongodb";
import {BaseModel} from "../core/base.model";
import {
    FindParam,
    InsertParam,
    UpdateParam,
    FindOneParam,
} from "../core/params";

export enum AddrStatus {
    DEFAULT = 1,
    NONE = 2,
    DELETED = 3,
}

export interface AddressInfo {
    _id ?: ObjectID,
    user_id: ObjectID,
    name: string,
    phone: string,
    loc: Location,
    address: string,
    status: AddrStatus,
    time ?: Date
}

export interface AddrUpdateOpt {
    name    ?: string,
    phone   ?: string,
    loc     ?: Location,
    address ?: string,
    time    ?: Date,
}

let addrProject = {
    _id: 1,
    loc: 1,
    name: 1,
    phone: 1,
    status: 1,
    address: 1
};

export default class AddressModel extends BaseModel {

    name() {
        return 'AddressModel';
    }

    constructor(coll: Collection) {
        super(coll);
    }

    checkExist(filter: {addrId?: ObjectID, userId?: ObjectID}): Promise<any> {
        let {addrId, userId} = filter;
        let match = {_id: addrId, user_id: userId};
        return this.findOne(new FindOneParam(utils.clearInvalidVal(match)));
    }

    getUserAddr(filter: {userId?: ObjectID}): Promise<any> {
        let match = {
            user_id: filter.userId,
            status: {$ne: AddrStatus.DELETED}
        };
        let options = new FindParam(match, addrProject);
        options.sort = {status: 1, time: -1};
        options.limit = 1;
        return this.find(options).then((addrs) => {
            return addrs && addrs[0] || null;
        });
    }

    setDefault(filter: {addrId: ObjectID, userId: ObjectID}): Promise<any> {
        let {addrId, userId} = filter;
        let noneOpt = {
            filter: {user_id: userId, status: AddrStatus.DEFAULT},
            update: {$set: {status: AddrStatus.NONE}}
        };
        let defaultOpt = {
            filter: {_id: addrId},
            update: {$set: {status: AddrStatus.DEFAULT}}
        };
        return Promise.all([
            this.updateOne(new UpdateParam(noneOpt.filter, noneOpt.update)),
            this.updateOne(new UpdateParam(defaultOpt.filter, defaultOpt.update))
        ]);
    }

    updateAddress(filter: {addrId: ObjectID}, info: AddrUpdateOpt): Promise<any> {
        let match = {_id: filter.addrId};
        let update = {$set: info};
        return this.updateOne(new UpdateParam(match, update));
    }

    delAddress(filter: {addrId: ObjectID}): Promise<any> {
        let match = {_id: filter.addrId};
        let update = {$set: {status: AddrStatus.DELETED}};
        return this.updateOne(new UpdateParam(match, update));
    }

    newAddress(addr: AddressInfo): Promise<any> {
        return this.insertOne(new InsertParam(addr));
    }

    getAddressList(filter: {userId: ObjectID}): Promise<any> {
        let match = {
            user_id: filter.userId,
            status: {$ne: AddrStatus.DELETED}
        };
        let options = new FindParam(match, addrProject);
        options.sort = {status: 1, time: -1};
        return this.find(options);
    }
}